package com.example.pdfexcelconverter.service.impl;

import technology.tabula.ObjectExtractor;
import technology.tabula.Page;
import technology.tabula.Table;
import technology.tabula.RectangularTextContainer;
import technology.tabula.extractors.SpreadsheetExtractionAlgorithm;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.io.MemoryUsageSetting;
import com.example.pdfexcelconverter.service.PdfToExcelService;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.List;

@Service
public class PdfToExcelServiceImpl implements PdfToExcelService {

    @Override
    public byte[] convertPdfToExcel(byte[] pdfBytes) throws Exception {
        // 创建一个新的工作簿
        Workbook workbook = new XSSFWorkbook();

        // 使用 PDFBox 加载 PDF 文件
        try (InputStream inputStream = new ByteArrayInputStream(pdfBytes)) {
            PDDocument pdfDocument = PDDocument.load(inputStream, MemoryUsageSetting.setupTempFileOnly());

            // 获取 PDF 的总页数
            int totalPages = pdfDocument.getNumberOfPages();

            // 使用 Tabula 提取表格数据
            ObjectExtractor extractor = new ObjectExtractor(pdfDocument);
            SpreadsheetExtractionAlgorithm algorithm = new SpreadsheetExtractionAlgorithm();

            // 遍历 PDF 的每一页
            for (int pageNumber = 1; pageNumber <= totalPages; pageNumber++) {
                // 创建一个新的 Sheet，命名为 "Page_X"
                Sheet sheet = workbook.createSheet("Page_" + pageNumber);

                // 提取当前页的表格数据
                Page page = extractor.extract(pageNumber);
                List<Table> tables = algorithm.extract(page);

                // 遍历提取的表格
                for (int tableIndex = 0; tableIndex < tables.size(); tableIndex++) {
                    Table table = tables.get(tableIndex);

                    // 获取表格的行数据
                    List<List<RectangularTextContainer>> rows = table.getRows();
                    if (rows != null) { // 防止空指针异常
                        for (int rowIdx = 0; rowIdx < rows.size(); rowIdx++) {
                            List<RectangularTextContainer> rowCells = rows.get(rowIdx);
                            Row excelRow = sheet.createRow(rowIdx); // 创建 Excel 行

                            // 遍历当前行的每个单元格
                            for (int colIdx = 0; colIdx < rowCells.size(); colIdx++) {
                                RectangularTextContainer cell = rowCells.get(colIdx);
                                Cell excelCell = excelRow.createCell(colIdx); // 创建 Excel 单元格
                                String cellText = cell.getText().trim(); // 获取单元格文本
                                excelCell.setCellValue(cellText.isEmpty() ? "" : cellText); // 设置单元格值

                                // 添加单元格样式
                                CellStyle cellStyle = workbook.createCellStyle();
                                cellStyle.setBorderBottom(BorderStyle.THIN);
                                cellStyle.setBorderTop(BorderStyle.THIN);
                                cellStyle.setBorderLeft(BorderStyle.THIN);
                                cellStyle.setBorderRight(BorderStyle.THIN);
                                cellStyle.setWrapText(true); // 自动换行
                                excelCell.setCellStyle(cellStyle);
                            }
                        }

                        // 在表格之间添加空行
                        if (tableIndex < tables.size() - 1) { // 避免在最后一个表格后添加空行
                            sheet.createRow(sheet.getLastRowNum() + 2).createCell(0).setCellValue(""); // 添加空行
                        }
                    }
                }
            }

            // 关闭 PDFBox 文档
            extractor.close();
            pdfDocument.close();
        }

        // 写入输出流
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            workbook.write(outputStream);
            workbook.close();
            return outputStream.toByteArray();
        }
    }
}